package com.foodorder.service;

import com.foodorder.entity.Order;
import com.foodorder.repository.OrderRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 支付超时处理服务
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class PaymentTimeoutService {
    
    private final OrderRepository orderRepository;
    private final OrderService orderService;
    private final InventoryService inventoryService;
    private final StringRedisTemplate redisTemplate;
    
    @Value("${app.payment.timeout.minutes:15}")
    private int paymentTimeoutMinutes;
    
    private static final String TIMEOUT_ORDER_KEY = "payment:timeout:order:";
    
    /**
     * 注册支付超时监控
     * 在订单创建时调用此方法
     * 
     * @param orderId 订单ID
     */
    public void registerPaymentTimeout(Long orderId) {
        try {
            String key = TIMEOUT_ORDER_KEY + orderId;
            // 设置Redis超时，过期时间为支付超时时间
            redisTemplate.opsForValue().set(key, orderId.toString(), paymentTimeoutMinutes, TimeUnit.MINUTES);
            
            log.info("注册支付超时监控，订单ID: {}, 超时时间: {}分钟", orderId, paymentTimeoutMinutes);
        } catch (Exception e) {
            log.error("注册支付超时监控失败，订单ID: {}", orderId, e);
        }
    }
    
    /**
     * 取消支付超时监控
     * 在订单支付成功时调用此方法
     * 
     * @param orderId 订单ID
     */
    public void cancelPaymentTimeout(Long orderId) {
        try {
            String key = TIMEOUT_ORDER_KEY + orderId;
            redisTemplate.delete(key);
            
            log.info("取消支付超时监控，订单ID: {}", orderId);
        } catch (Exception e) {
            log.error("取消支付超时监控失败，订单ID: {}", orderId, e);
        }
    }
    
    /**
     * 定时任务：检查并处理支付超时的订单
     * 每分钟执行一次
     */
    @Scheduled(fixedRate = 60000) // 每分钟执行一次
    @Async
    @Transactional
    public void processPaymentTimeouts() {
        try {
            // 计算超时时间
            LocalDateTime timeoutThreshold = LocalDateTime.now().minusMinutes(paymentTimeoutMinutes);
            
            // 查找超时的待支付订单
            List<Order> timeoutOrders = orderRepository.findPendingPaymentOrdersBeforeTime(timeoutThreshold);
            
            if (timeoutOrders.isEmpty()) {
                return;
            }
            
            log.info("检测到 {} 个支付超时订单", timeoutOrders.size());
            
            for (Order order : timeoutOrders) {
                try {
                    processTimeoutOrder(order);
                } catch (Exception e) {
                    log.error("处理支付超时订单失败，订单ID: {}", order.getId(), e);
                }
            }
            
        } catch (Exception e) {
            log.error("处理支付超时订单定时任务执行失败", e);
        }
    }
    
    /**
     * 处理单个超时订单
     * 
     * @param order 超时订单
     */
    private void processTimeoutOrder(Order order) {
        try {
            log.info("开始处理支付超时订单，订单号: {}, 创建时间: {}", 
                order.getOrderNo(), order.getCreatedAt());
            
            // 取消订单
            orderService.cancelOrder(order.getId(), "支付超时自动取消");
            
            // 清除超时监控
            cancelPaymentTimeout(order.getId());
            
            // 发送通知（可扩展）
            sendTimeoutNotification(order);
            
            log.info("支付超时订单处理完成，订单号: {}", order.getOrderNo());
            
        } catch (Exception e) {
            log.error("处理支付超时订单失败，订单ID: {}", order.getId(), e);
            throw e;
        }
    }
    
    /**
     * 发送超时通知
     * 
     * @param order 超时订单
     */
    private void sendTimeoutNotification(Order order) {
        try {
            // 这里可以集成短信、微信模板消息等通知方式
            log.info("订单支付超时通知，用户ID: {}, 订单号: {}", 
                order.getUserId(), order.getOrderNo());
            
            // TODO: 实现具体的通知逻辑
            // 1. 微信模板消息通知用户
            // 2. 商家订单取消通知
            // 3. 系统内消息记录
            
        } catch (Exception e) {
            log.error("发送超时通知失败，订单ID: {}", order.getId(), e);
        }
    }
    
    /**
     * 手动处理支付超时订单
     * 
     * @param orderId 订单ID
     */
    @Transactional
    public void handlePaymentTimeoutManually(Long orderId) {
        Order order = orderRepository.findById(orderId).orElse(null);
        if (order == null) {
            throw new RuntimeException("订单不存在");
        }
        
        if (order.getStatus() != Order.OrderStatus.PENDING_PAYMENT) {
            throw new RuntimeException("订单状态不是待支付，无法处理超时");
        }
        
        processTimeoutOrder(order);
    }
    
    /**
     * 检查订单是否已超时
     * 
     * @param orderId 订单ID
     * @return 是否超时
     */
    public boolean isOrderTimeout(Long orderId) {
        Order order = orderRepository.findById(orderId).orElse(null);
        if (order == null || order.getStatus() != Order.OrderStatus.PENDING_PAYMENT) {
            return false;
        }
        
        LocalDateTime timeoutThreshold = LocalDateTime.now().minusMinutes(paymentTimeoutMinutes);
        return order.getCreatedAt().isBefore(timeoutThreshold);
    }
    
    /**
     * 获取订单剩余支付时间（分钟）
     * 
     * @param orderId 订单ID
     * @return 剩余时间（分钟），负数表示已超时
     */
    public long getRemainingPaymentTime(Long orderId) {
        Order order = orderRepository.findById(orderId).orElse(null);
        if (order == null || order.getStatus() != Order.OrderStatus.PENDING_PAYMENT) {
            return -1;
        }
        
        LocalDateTime timeoutTime = order.getCreatedAt().plusMinutes(paymentTimeoutMinutes);
        LocalDateTime now = LocalDateTime.now();
        
        if (now.isAfter(timeoutTime)) {
            return -1; // 已超时
        }
        
        return java.time.Duration.between(now, timeoutTime).toMinutes();
    }
    
    /**
     * 批量处理支付超时订单
     * 
     * @param orderIds 订单ID列表
     */
    @Async
    @Transactional
    public void batchProcessPaymentTimeouts(List<Long> orderIds) {
        for (Long orderId : orderIds) {
            try {
                handlePaymentTimeoutManually(orderId);
            } catch (Exception e) {
                log.error("批量处理支付超时订单失败，订单ID: {}", orderId, e);
            }
        }
    }
    
    /**
     * 获取系统配置的支付超时时间
     * 
     * @return 支付超时时间（分钟）
     */
    public int getPaymentTimeoutMinutes() {
        return paymentTimeoutMinutes;
    }
    
    /**
     * 更新支付超时时间配置
     * 
     * @param timeoutMinutes 新的超时时间（分钟）
     */
    public void updatePaymentTimeout(int timeoutMinutes) {
        if (timeoutMinutes < 5 || timeoutMinutes > 60) {
            throw new IllegalArgumentException("支付超时时间必须在5-60分钟之间");
        }
        
        this.paymentTimeoutMinutes = timeoutMinutes;
        log.info("更新支付超时时间配置为: {}分钟", timeoutMinutes);
    }
} 